package com.alibaba.citrus.cr.platform.enhance.facade.service.diff.sap;

import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import com.alibaba.acm.shaded.com.google.common.collect.Lists;
import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.platform.enhance.facade.service.diff.common.constant.DiffResultStatus;
import com.alibaba.citrus.cr.platform.enhance.facade.service.diff.common.constant.DiffTypeEnum;
import com.alibaba.citrus.cr.platform.enhance.functions.diff.common.constant.DiffStrategyRouteDict;
import com.alibaba.citrus.cr.platform.enhance.functions.diff.common.template.StandardTemplateDiff;
import com.alibaba.citrus.cr.platform.enhance.functions.diff.sap.template.SalesMainOrderStatusStandardTemplate;
import com.alibaba.citrus.cr.platform.enhance.functions.diff.sap.template.SalesSubOrderStatusStandardTemplate;
import com.alibaba.citrus.cr.platform.enhance.repository.DiffErrorRepository;
import com.alibaba.citrus.cr.platform.enhance.repository.SalesOrderLineQueryServiceRepository;
import com.alibaba.citrus.cr.platform.enhance.repository.SalesOrderQueryServiceRepository;
import com.alibaba.citrus.cr.platform.enhance.repository.model.diff.activity.QuerySalesOrderLineParam;
import com.alibaba.citrus.cr.platform.enhance.repository.model.diff.activity.QuerySalesOrderParam;
import com.alibaba.citrus.cr.platform.enhance.repository.model.diff.common.DiffErrorDTO;
import com.alibaba.citrus.cr.platform.enhance.repository.model.diff.common.OrderStatusFieldDTO;
import com.alibaba.citrus.cr.platform.enhance.repository.model.diff.common.SalesOrderDTO;
import com.alibaba.citrus.cr.platform.enhance.repository.model.diff.common.SalesOrderLineDTO;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.lattice2.epoch.sdk.model.Result;

import com.epoch.app.crb2btradecenter.enums.OrderStatus;
import com.epoch.app.crplatformenhance.model.dto.SalesOrderStatusDiffCheckRequest;
import com.epoch.app.crplatformenhance.salesorderstatusdiffcheck.service.SalesOrderStatusDiffCheckService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

/**
 * @author hanguo
 * @date 2022/2/17
 * @Description 销售订单状态对账
 */
@Service
@Primary
public class SaleOrderStatusDiffCheckServiceImpl implements SalesOrderStatusDiffCheckService {

    @Resource
    private SalesOrderQueryServiceRepository salesOrderQueryServiceRepository;


    @Resource
    private SalesOrderLineQueryServiceRepository salesOrderLineQueryServiceRepository;

    @Resource
    private ApplicationContext applicationContext;

    @Resource
    private DiffErrorRepository diffErrorRepository;

    @Resource
    private StandardTemplateDiff standardTemplateDiff;
    /**
     * 日志
     */
    private Log log = Log.getLogger(SaleOrderStatusDiffCheckServiceImpl.class);

    @Override
    @FacadeInvoker
    public Result<String> salesMainOrderStatus(SalesOrderStatusDiffCheckRequest request) {
        //1.定时任务查询五分钟内的销售主单数据
        //2.遍历数据，取每条数据的状态信息，获取对应的字段校验标准模板
        //3.和标准模板对比解决空的问题
        //4.获取数据处理器，比对字段间的关系，解决错的问题

        QuerySalesOrderParam salesOrderParam = new QuerySalesOrderParam();

//        salesOrderParam.setLimit(30);
//        salesOrderParam.setStatus(ActivityFlowEnum.ACTIVITY_OCCUPY.getStatus());
//        salesOrderParam.setStart(0);
//        LocalDateTime localDateTime = LocalDateTime.now();
//        localDateTime = localDateTime.minusMinutes(5);
//        Date beforeMinutes = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
//        salesOrderParam.setStartModifyTime(beforeMinutes);
//        salesOrderParam.setEndModifyTime(new Date());
        salesOrderParam.setStart(request.getStart());
        salesOrderParam.setLimit(request.getLimit());
        salesOrderParam.setStartModifyTime(request.getStartDiffDate());
        salesOrderParam.setEndModifyTime(request.getEndDiffDate());
        Result<List<SalesOrderDTO>> salesOrderDTOS = salesOrderQueryServiceRepository.queryByGmtModify(salesOrderParam);
        int total = salesOrderDTOS.getTotal();
        boolean isFirst = true;
        while (salesOrderParam.getStart() < total) {
            if (!isFirst) {
                salesOrderDTOS = salesOrderQueryServiceRepository.queryByGmtModify(salesOrderParam);
            } else {
                isFirst = false;
            }
            List<SalesOrderDTO> salesOrderDTOList = salesOrderDTOS.getResult();
            if (CollectionUtils.isNotEmpty(salesOrderDTOList)) {

                //遍历主单进行状态对账
                List<DiffErrorDTO> diffErrorDTOS = doDiffForSalesMainOrder(salesOrderDTOList);

                //保存错误对账记录
                if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(diffErrorDTOS)) {
                    //批量保存差错记录
                    diffErrorRepository.batchSaveDiffErrorList(diffErrorDTOS);
                }
            }
            salesOrderParam.setStart(salesOrderParam.getStart() + salesOrderParam.getLimit());
        }

        return Result.success("true");
    }

    /**
     * 销售主单状态对账
     *
     * @param salesOrderDTOS
     * @return
     */
    private List<DiffErrorDTO> doDiffForSalesMainOrder(List<SalesOrderDTO> salesOrderDTOS) {

        List<DiffErrorDTO> diffErrorDTOList = Lists.newArrayList();

        for (SalesOrderDTO salesOrderDTO : salesOrderDTOS) {
            try {
                //获取状态
                Integer status = salesOrderDTO.getStatus();
                //获取对账模板
                Set<OrderStatusFieldDTO> mainOrderTemplateFieldSet = SalesMainOrderStatusStandardTemplate.obtainTemplateFieldSet(status.toString());
               if(CollectionUtils.isEmpty(mainOrderTemplateFieldSet)){
                   continue;
               }

                //解决空的问题
                Result<String> diffResult = standardTemplateDiff.checkForStatus(mainOrderTemplateFieldSet, salesOrderDTO
                        , salesOrderDTO.getClass()
                        , SalesMainOrderStatusStandardTemplate.obtainIgnoreFieldSet());

                if (!diffResult.isSuccess()) {
                    //埋点
                    log.error("SaleOrderStatusDiffCheckServiceImpl#salesMainOrderDiffCheck_fail");
                    DiffErrorDTO diffErrorDto = buildSalesMainOrderDiffErrorDTO(salesOrderDTO, status, diffResult.getMessage());
                    diffErrorDTOList.add(diffErrorDto);
                }


            } catch (Exception e) {
                //埋点
                log.error("SaleOrderStatusDiffCheckServiceImpl#salesMainOrderDiffCheck_fail");
                log.error("对账出错了", e);
                DiffErrorDTO diffErrorDto = buildSalesMainOrderDiffErrorDTO(salesOrderDTO, null, "对账出异常了！");
                diffErrorDTOList.add(diffErrorDto);
            }

        }

        return diffErrorDTOList;
    }

    /**
     * 构建销售主单对账差错记录数据
     *
     * @param salesOrderDTO DB数据
     * @param status        状态
     * @param diffResult    错误信息
     * @return
     */
    private DiffErrorDTO buildSalesMainOrderDiffErrorDTO(SalesOrderDTO salesOrderDTO, Integer status, String diffResult) {
        //1. 封装差错记录
        DiffErrorDTO diffErrorDto = DiffErrorDTO.builder()
                .diffType(DiffTypeEnum.SALES_MAIN_ORDER_STATUS.getDiffType())
                //业务流程描述
                .diffDesc(DiffTypeEnum.SALES_MAIN_ORDER_STATUS.getDiffDesc())
                //对账结果描述
                .result(diffResult)
                .diffData1(JSON.toJSONString("{status:" + status + "}"))
                .diffData2(JSON.toJSONString(salesOrderDTO))
                .strategyRoute(DiffStrategyRouteDict.SALES_MAIN_ORDER_STATUS.getStrategyCode())
                .mainOrderId(salesOrderDTO.getId().toString())
                .status(DiffResultStatus.FAIL.getStatus()).build();
        return diffErrorDto;
    }

    @Override
    public Result<String> salesSubOrderStatus(SalesOrderStatusDiffCheckRequest request) {

        //1.定时任务查询五分钟内的销售子单数据
        //2.遍历数据，取每条数据的状态信息，获取对应的字段校验标准模板
        //3.和标准模板对比解决空的问题
        //4.获取数据处理器，比对字段间的关系，解决错的问题

        QuerySalesOrderLineParam salesOrderLineParam = new QuerySalesOrderLineParam();

//        param.setLimit(30);
//        param.setStatus(ActivityFlowEnum.ACTIVITY_OCCUPY.getStatus());
//        param.setStart(0);
//        LocalDateTime localDateTime = LocalDateTime.now();
//        localDateTime = localDateTime.minusMinutes(5);
//        Date beforeMinutes = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
//        param.setStartModifyTime(beforeMinutes);
//        param.setEndModifyTime(new Date());
        salesOrderLineParam.setStart(request.getStart());
        salesOrderLineParam.setLimit(request.getLimit());
        salesOrderLineParam.setStartModifyTime(request.getStartDiffDate());
        salesOrderLineParam.setEndModifyTime(request.getEndDiffDate());
        Result<List<SalesOrderLineDTO>> salesOrderLineDTOS = salesOrderLineQueryServiceRepository.querySalesOrderLineByGmtModifyDesc(salesOrderLineParam);
        int total = salesOrderLineDTOS.getTotal();
        boolean isFirst = true;
        while (salesOrderLineParam.getStart() < total) {
            if (!isFirst) {
                salesOrderLineDTOS = salesOrderLineQueryServiceRepository.querySalesOrderLineByGmtModifyDesc(salesOrderLineParam);
            } else {
                isFirst = false;
            }
            List<SalesOrderLineDTO> salesOrderLineDTOList = salesOrderLineDTOS.getResult();
            if (CollectionUtils.isNotEmpty(salesOrderLineDTOList)) {

                //遍历子单进行状态对账
                List<DiffErrorDTO> diffErrorDTOS = doDiffForSalesSubOrder(salesOrderLineDTOList);

                //保存错误对账记录
                if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(diffErrorDTOS)) {
                    //批量保存差错记录
                    diffErrorRepository.batchSaveDiffErrorList(diffErrorDTOS);
                }
            }
            salesOrderLineParam.setStart(salesOrderLineParam.getStart() + salesOrderLineParam.getLimit());
        }

        return Result.success("true");
    }

    /**
     * 销售子单状态对账
     *
     * @param salesOrderLineDTOList
     * @return
     */
    private List<DiffErrorDTO> doDiffForSalesSubOrder(List<SalesOrderLineDTO> salesOrderLineDTOList) {

        List<DiffErrorDTO> diffErrorDTOList = Lists.newArrayList();

        for (SalesOrderLineDTO salesOrderLineDTO : salesOrderLineDTOList) {
            try {
                //获取状态
                Integer status = salesOrderLineDTO.getStatus();

                Set<OrderStatusFieldDTO> subOrderTemplateFieldSet = null;
                //状态为4单独处理
                if (OrderStatus.COMPLETED.getCode().equals(status) &&
                        StringUtils.isBlank(salesOrderLineDTO.getRefuseReasonCode())
                        || !OrderStatus.COMPLETED.getCode().equals(status)) {
                    //获取对账模板
                    subOrderTemplateFieldSet = SalesSubOrderStatusStandardTemplate.obtainTemplateFieldSet(status.toString());
                } else {
                    continue;
                }

                //解决空的问题
                Result<String> diffResult = standardTemplateDiff.checkForStatus(subOrderTemplateFieldSet, salesOrderLineDTO
                        , salesOrderLineDTO.getClass()
                        , SalesMainOrderStatusStandardTemplate.obtainIgnoreFieldSet());
                if (!diffResult.isSuccess()) {
                    //埋点
                    log.error("SaleOrderStatusDiffCheckServiceImpl#salesSubOrderDiffCheck_fail");
                    DiffErrorDTO diffErrorDto = buildSalesSubOrderDiffErrorDTO(salesOrderLineDTO, status, diffResult.getMessage());
                    diffErrorDTOList.add(diffErrorDto);
                }

                //处理错的问题，目前只有状态为4需要进行校验
                if (OrderStatus.COMPLETED.getCode().equals(salesOrderLineDTO.getStatus())) {
                    Integer quantity = salesOrderLineDTO.getQuantity();
                    String deliveryAmount = salesOrderLineDTO.getDeliveryAmount();
                    if (!StringUtils.equals(deliveryAmount, quantity.toString())) {
                        //埋点
                        log.error("SaleOrderStatusDiffCheckServiceImpl#salesSubOrderDiffCheck_fail");
                        DiffErrorDTO diffErrorDto = buildSalesSubOrderDiffErrorDTO(salesOrderLineDTO, status, "发货和收货数量不一致!" + "发货：" + deliveryAmount + "收货：" + quantity);
                        diffErrorDTOList.add(diffErrorDto);
                    }

                }


            } catch (Exception e) {
                //埋点
                log.error("SaleOrderStatusDiffCheckServiceImpl#salesSubOrderDiffCheck_fail");
                log.error("对账出错了", e);
                DiffErrorDTO diffErrorDto = buildSalesSubOrderDiffErrorDTO(salesOrderLineDTO, null, "对账出异常了！");
                diffErrorDTOList.add(diffErrorDto);
            }

        }

        return diffErrorDTOList;
    }

    private DiffErrorDTO buildSalesSubOrderDiffErrorDTO(SalesOrderLineDTO salesOrderLineDTO, Integer status, String diffResult) {
        //1. 封装差错记录
        DiffErrorDTO diffErrorDto = DiffErrorDTO.builder()
                .diffType(DiffTypeEnum.SALES_SUB_ORDER_STATUS.getDiffType())
                //业务流程描述
                .diffDesc(DiffTypeEnum.SALES_SUB_ORDER_STATUS.getDiffDesc())
                //对账结果描述
                .result(diffResult)
                .diffData1(JSON.toJSONString("{status:" + status + "}"))
                .diffData2(JSON.toJSONString(salesOrderLineDTO))
                .strategyRoute(DiffStrategyRouteDict.SALES_MAIN_ORDER_STATUS.getStrategyCode())
                .mainOrderId(salesOrderLineDTO.getMainOrderId())
                .subOrderId(salesOrderLineDTO.getId().toString())
                .status(DiffResultStatus.FAIL.getStatus()).build();
        return diffErrorDto;
    }
}
